<template>
  <div v-if="currentComponent" class="condition-form">
    <span v-if="currentComponent.label" class="nlabel">{{ currentComponent.label }}</span>
    <component
      :is="currentComponent.componentValue"
      ref="conditionForm"
      v-model:value="editConditionData.value"
      class="input-width"
      :column-info="columnInfo"
      :dynamic-field-list="dynamicFieldList"
      :filter-dynamic-field-func="filterDynamicFieldFunc"
      :condition-data="conditionData"
      v-bind="currentComponent.props"
    />
    <span class="error-label">{{ errorMsg }}</span>
  </div>
</template>

<script lang="ts">
  import { defineComponent, ref, watch, computed } from 'vue'
  import { useI18n } from 'vue-i18n'
  import { getComponent } from './conditionFormConfig'
  import { isArray } from '@/utils/is'

  export default defineComponent({
    props: {
      columnInfo: {
        type: Object as PropType<FiledListType>,
        require: true,
        default: () => ({ type: 'VARCHAR' })
      },
      conditionData: {
        type: Object as PropType<FormItemVisibleConditionData>,
        default: () => ({
          conditionType: '',
          value: ''
        })
      },
      // 动态值下拉字段
      dynamicFieldList: {
        type: Array,
        default: () => []
      },
      filterDynamicFieldFunc: {
        type: Function as PropType<(columnInfo: FiledListType, fieldList: FiledListType[]) => FiledListType[]>
      }
    },
    setup(props) {
      const { t } = useI18n()

      const conditionForm = ref()

      const errorMsg = ref<string>('')
      const editConditionData = ref()

      watch(
        () => props.conditionData,
        () => {
          editConditionData.value = props.conditionData
        },
        {
          immediate: true,
          deep: true
        }
      )

      // 调用组件内部的校验方法
      function customValidate() {
        const component = conditionForm.value
        if (component && component.validate) {
          return component.validate()
        }
        return Promise.resolve()
      }

      // 组件必填校验
      function requiredValidate() {
        const { value } = editConditionData.value
        if ((value !== 0 && !value) || (isArray(value) && !value.length)) {
          return Promise.reject(t('placeholderInput'))
        }
        return Promise.resolve()
      }

      const validatorMap = {
        require: requiredValidate,
        custom: customValidate
      }
      // 校验表达式的值
      function validate() {
        errorMsg.value = '' // 清空校验错误信息
        const { validate } = currentComponent.value || {}
        if (validate && validatorMap[validate]) {
          return validatorMap[validate]().catch(error => {
            errorMsg.value = error
            return Promise.reject()
          })
        }

        return Promise.resolve()
      }

      watch(
        () => editConditionData.value.value,
        () => {
          // 条件表达式的值发生变化，对结果进行校验
          validate()
        },
        {
          deep: true
        }
      )

      const currentComponent = computed(() => {
        const { componentKey, fixedAndDynamic } = props.columnInfo
        const { conditionType } = props.conditionData || {}
        /**
         * +++++++++++++++++++++++
         * 条件不是空或者非空，且需要显示固定值和动态值的时候使用动态值和固定值组件
         * +++++++++++++++++++++++
         */
        const showFixedAndDynamic = fixedAndDynamic && !['IS_NULL', 'IS_NOT_NULL'].includes(conditionType)
        return getComponent(componentKey, conditionType, showFixedAndDynamic)
      })
      return {
        editConditionData,
        currentComponent,
        errorMsg,
        conditionForm
      }
    }
  })
</script>

<style lang="less" scoped>
  .condition-form {
    display: flex;
    align-items: center;

    .nlabel {
      margin-right: 10px;
    }

    .error-label {
      color: red;
      margin-left: 10px;
    }

    .input-width {
      width: 300px;
    }
  }
</style>
